import { View, Text, Button } from '@tarojs/components'
import { useLoad, showToast } from '@tarojs/taro'
import { useState, useRef, useEffect } from 'react'
import './index.scss'

// 定义区块接口
interface Block {
  index: number
  timestamp: string
  data: string
  previousHash: string
  hash: string
  nonce: number
}

// 简化的哈希函数
const calculateHash = (index: number, timestamp: string, data: string, previousHash: string, nonce: number): string => {
  const str = `${index}${timestamp}${data}${previousHash}${nonce}`
  let hash = 0
  for (let i = 0; i < str.length; i++) {
    const char = str.charCodeAt(i)
    hash = ((hash << 5) - hash) + char
    hash = hash & hash // 转换为32位整数
  }
  return Math.abs(hash).toString(16)
}

export default function BlockchainDemo() {
  const [blockchain, setBlockchain] = useState<Block[]>([])
  const [data, setData] = useState('')
  const [difficulty, setDifficulty] = useState(4) // 挖矿难度
  const [logs, setLogs] = useState<string[]>([])
  const logEndRef = useRef<HTMLDivElement>(null)
  const [showLogs, setShowLogs] = useState(false)

  // 自动滚动到最新日志
  useEffect(() => {
    if (logEndRef.current) {
      logEndRef.current.scrollIntoView({ behavior: 'smooth' })
    }
  }, [logs])

  // 添加日志
  const addLog = (message: string) => {
    setLogs(prev => [...prev, `[${new Date().toLocaleTimeString()}] ${message}`])
  }

  // 清空日志
  const clearLogs = () => {
    setLogs([])
  }

  useLoad(() => {
    addLog('区块链演示页面已加载')
    // 创建创世区块
    if (blockchain.length === 0) {
      createGenesisBlock()
    }
  })

  // 创建创世区块
  const createGenesisBlock = () => {
    addLog('正在创建创世区块...')
    const genesisBlock: Block = {
      index: 0,
      timestamp: new Date().toISOString(),
      data: 'Genesis Block',
      previousHash: '0',
      hash: '',
      nonce: 0
    }
    genesisBlock.hash = calculateHash(
      genesisBlock.index,
      genesisBlock.timestamp,
      genesisBlock.data,
      genesisBlock.previousHash,
      genesisBlock.nonce
    )
    setBlockchain([genesisBlock])
    addLog(`创世区块已创建，哈希值: ${genesisBlock.hash}`)
  }

  // 获取最新区块
  const getLatestBlock = (): Block => {
    return blockchain[blockchain.length - 1]
  }

  // 挖矿生成新区块
  const mineBlock = (data: string) => {
    const previousBlock = getLatestBlock()
    const newIndex = previousBlock.index + 1
    const newTimestamp = new Date().toISOString()
    const newPreviousHash = previousBlock.hash
    let newNonce = 0
    let newHash = ''
    let attempts = 0
    
    addLog(`开始挖掘区块 #${newIndex}，难度: ${difficulty}`)
    addLog(`前一区块哈希: ${newPreviousHash}`)
    addLog(`区块数据: ${data}`)

    // 挖矿过程 - 找到满足难度条件的哈希值
    do {
      newNonce++
      newHash = calculateHash(newIndex, newTimestamp, data, newPreviousHash, newNonce)
      attempts++
      
      // 每1000次尝试打印一次日志，避免日志过多
      if (attempts % 1000 === 0) {
        addLog(`尝试 #${attempts}: 哈希值: ${newHash}`)
      }
    } while (!newHash.startsWith('0'.repeat(difficulty)))

    addLog(`挖矿完成! 共尝试 ${attempts} 次，Nonce值: ${newNonce}`)
    addLog(`新区块哈希值: ${newHash}`)

    const newBlock: Block = {
      index: newIndex,
      timestamp: newTimestamp,
      data: data,
      previousHash: newPreviousHash,
      hash: newHash,
      nonce: newNonce
    }

    return newBlock
  }

  // 添加新区块
  const addBlock = () => {
    if (!data.trim()) {
      showToast({
        title: '请输入区块数据',
        icon: 'none'
      })
      return
    }

    showToast({
      title: '开始挖矿...',
      icon: 'loading',
      duration: 20000
    })
    
    // 自动显示日志区域
    setShowLogs(true)

    // 模拟挖矿延迟
    setTimeout(() => {
      const newBlock = mineBlock(data)
      const newBlockchain = [...blockchain, newBlock]
      setBlockchain(newBlockchain)
      setData('')
      
      showToast({
        title: `区块 ${newBlock.index} 已添加`,
        icon: 'success'
      })
    }, 1000)
  }

  // 验证区块链完整性
  const validateChain = () => {
    addLog('开始验证区块链完整性...')
    addLog(`区块链包含 ${blockchain.length} 个区块`)
    
    for (let i = 1; i < blockchain.length; i++) {
      const currentBlock = blockchain[i]
      const previousBlock = blockchain[i - 1]
      
      addLog(`验证区块 #${i}`)
      
      // 验证当前区块的哈希
      const recalculatedHash = calculateHash(
        currentBlock.index,
        currentBlock.timestamp,
        currentBlock.data,
        currentBlock.previousHash,
        currentBlock.nonce
      )
      
      if (currentBlock.hash !== recalculatedHash) {
        addLog(`✖ 区块 #${i} 哈希验证失败! 预期: ${currentBlock.hash}，计算: ${recalculatedHash}`)
        return false
      } else {
        addLog(`✓ 区块 #${i} 哈希验证通过`)
      }

      // 验证区块链接
      if (currentBlock.previousHash !== previousBlock.hash) {
        addLog(`✖ 区块 #${i} 链接验证失败! 预期: ${previousBlock.hash}，实际: ${currentBlock.previousHash}`)
        return false
      } else {
        addLog(`✓ 区块 #${i} 链接验证通过`)
      }
    }
    
    addLog('✓ 区块链完整性验证通过')
    return true
  }

  // 检查区块链状态
  const checkBlockchain = () => {
    // 自动显示日志区域
    setShowLogs(true)
    
    const isValid = validateChain()
    showToast({
      title: isValid ? '区块链验证通过' : '区块链已被篡改',
      icon: isValid ? 'success' : 'none'
    })
  }

  return (
    <View className='index'>
      <Text className='title'>区块链演示</Text>
      
      <View className='input-group'>
        <Text className='label'>区块数据:</Text>
        <input
          type='text'
          value={data}
          onChange={(e) => setData(e.target.value)}
          placeholder='请输入区块数据'
          className='input'
        />
      </View>

      <View className='input-group'>
        <Text className='label'>挖矿难度:</Text>
        <input
          type='number'
          min='1'
          max='6'
          value={difficulty}
          onChange={(e) => setDifficulty(parseInt(e.target.value))}
          className='input small'
        />
      </View>

      <View className='button-group'>
        <Button onClick={addBlock} type='primary'>
          挖矿并添加区块
        </Button>
        <Button onClick={checkBlockchain} type='default'>
          验证区块链
        </Button>
        <Button onClick={() => setShowLogs(!showLogs)} type='default'>
          {showLogs ? '隐藏日志' : '显示日志'}
        </Button>
        <Button onClick={clearLogs} type='default' disabled={logs.length === 0}>
          清空日志
        </Button>
      </View>

      <View className='blockchain-info'>
        <Text className='subtitle'>区块链信息</Text>
        <Text>区块数量: {blockchain.length}</Text>
        {blockchain.length > 0 && (
          <Text>最新区块索引: {getLatestBlock().index}</Text>
        )}
      </View>

      {/* 实时日志显示区域 */}
      {showLogs && (
        <View className='logs-container'>
          <Text className='subtitle'>操作日志</Text>
          <View className='logs'>
            {logs.map((log, index) => (
              <Text key={index} className='log-entry'>{log}</Text>
            ))}
            <div ref={logEndRef} />
          </View>
        </View>
      )}
    </View>
  )
}
